import axios from '../utils/axios';
import { useUserStore } from '../stores/user';

export interface TaskCourse {
  name: string;
  status: string;
  description: string;
  completion: number;
}

export interface Task {
  id: number;
  title: string;
  description: string;
  startTime: string;
  endTime: string;
  status: string;
  priority: string;
  supervisorId: number;
  supervisorName: string;
  assigneeId: number;
  assigneeName: string;
  projectId: number;
  completed: boolean;
  reviewNeeded: boolean;
  createTime: string;
  updateTime: string;
  type?: string;       // Task type, such as Draft, Midterm, Final Draft
  progress?: number;   // Task progress percentage
  lastSubmissionTime?: string; // Last submission time
  submissionCount?: number; // Number of submissions
}

export interface TaskRequest {
  titleTemplate: string;
  descriptionTemplate: string;
  priority: string;
  status: string;
  startTime: string;
  endTime: string;
  assignToAllStudents: boolean;
}

export interface TaskSubmission {
  id: number;
  taskId: number;
  taskTitle: string;
  filePath: string;
  originalFilename: string;
  fileType: string;
  fileSize: number;
  submitterId: number;
  submitterName: string;
  submissionTime: string;
  comment: string;
}

/**
 * Task Evaluation interface definition
 */
export interface TaskEvaluation {
  id: number;
  taskId: number;
  taskTitle: string;
  score: number;
  comment: string;
  evaluatedBy: number;
  evaluatorName: string;
  evaluationTime: string;
}

// Task cache, used to improve performance
const taskCache = new Map<string, {
  tasks: Task[],
  timestamp: number
}>();

// Cache expiration time (milliseconds)
const CACHE_EXPIRY = 5000; // 5 seconds, reduce the cache time to ensure data updates more timely

// ==================== Supervisor Interface ====================

/**
 * Creates a task (supervisor view).
 * @param taskData The task data to create.
 * @returns A promise that resolves to a Task object.
 */
export const createTask = async (taskData: any): Promise<Task> => {
  console.log('Creating Task API call, data:', taskData);
  const response = await axios.post<Task>('/api/supervisor/tasks', taskData);

  // If the task is associated with a project, clear the task cache for that project
  if (taskData.projectId) {
    // Clear cache
    const cacheKey = `project-tasks-${taskData.projectId}`;
    taskCache.delete(cacheKey);
  }

  return response.data;
}

/**
 * Updates a task (supervisor view).
 * @param id The ID of the task to update.
 * @param taskData The task data to update.
 * @returns A promise that resolves to a Task object.
 */
export const updateTask = async (id: number, taskData: any): Promise<Task> => {
  console.log('Updating Task API call, Task ID:', id, 'data:', taskData);
  const response = await axios.put<Task>(`/api/supervisor/tasks/${id}`, taskData);

  // If the task is associated with a project, clear the task cache for that project
  if (taskData.projectId) {
    // Clear cache
    const cacheKey = `project-tasks-${taskData.projectId}`;
    taskCache.delete(cacheKey);
  }

  return response.data;
}

/**
 * Gets the details of a task (supervisor view).
 * @param id The ID of the task.
 * @returns A promise that resolves to a Task object.
 */
export const getTaskDetail = async (id: number): Promise<Task> => {
  const response = await axios.get<Task>(`/api/supervisor/tasks/${id}`);
  return response.data;
}

/**
 * Deletes a task (supervisor view).
 * @param id The ID of the task to delete.
 * @returns A promise that resolves to a boolean indicating whether the deletion was successful.
 */
export const deleteTask = async (id: number): Promise<boolean> => {
  // Get the task information first to get the projectId
  try {
    const task = await getTaskDetail(id);
    const response = await axios.delete(`/api/supervisor/tasks/${id}`);

    // If the task is associated with a project, clear the task cache for that project
    if (task && task.projectId) {
      // Clear cache
      const cacheKey = `project-tasks-${task.projectId}`;
      taskCache.delete(cacheKey);
    }

    return response.status === 200;
  } catch (error) {
    console.error('Failed to delete task:', error);
    return false;
  }
}

/**
 * Gets all tasks created by a supervisor.
 * @param supervisorId The ID of the supervisor.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getSupervisorTasks = async (supervisorId: number): Promise<Task[]> => {
  const response = await axios.get<Task[]>(`/api/supervisor/tasks?supervisorId=${supervisorId}`);
  return response.data;
}

/**
 * Gets the tasks with the specified status created by a supervisor.
 * @param supervisorId The ID of the supervisor.
 * @param status The status to filter tasks by.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getSupervisorTasksByStatus = async (supervisorId: number, status: string): Promise<Task[]> => {
  const response = await axios.get<Task[]>(`/api/supervisor/tasks/status/${status}?supervisorId=${supervisorId}`);
  return response.data;
}

/**
 * Assigns a task to a student.
 * @param taskId The ID of the task to assign.
 * @param studentId The ID of the student to assign the task to.
 * @returns A promise that resolves to a Task object.
 */
export const assignTaskToStudent = async (taskId: number, studentId: number): Promise<Task> => {
  const response = await axios.put<Task>(`/api/supervisor/tasks/${taskId}/assign/${studentId}`);
  return response.data;
}

/**
 * Updates the status of a task (supervisor view).
 * @param id The ID of the task to update.
 * @param status The new status for the task.
 * @returns A promise that resolves to a Task object.
 */
export const updateTaskStatus = async (id: number, status: string): Promise<Task> => {
  const response = await axios.put<Task>(`/api/supervisor/tasks/${id}/status`, { status });
  return response.data;
}

// ==================== Student Interface ====================

/**
 * Gets all tasks assigned to a student.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getMyTasks = async (): Promise<Task[]> => {
  const response = await axios.get<Task[]>('/api/user/tasks');
  return response.data;
}

/**
 * Gets tasks assigned to a student with the specified status.
 * @param status The status to filter tasks by.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getMyTasksByStatus = async (status: string): Promise<Task[]> => {
  const response = await axios.get<Task[]>(`/api/user/tasks/status/${status}`);
  return response.data;
}

/**
 * Gets the details of a task (student view).
 * @param id The ID of the task.
 * @returns A promise that resolves to a Task object.
 */
export const getMyTaskDetail = async (id: number): Promise<Task> => {
  const response = await axios.get<Task>(`/api/user/tasks/${id}`);
  return response.data;
}

/**
 * Updates the completion status of a task (student view).
 * @param id The ID of the task to update.
 * @param completed Whether the task is completed or not.
 * @returns A promise that resolves to a Task object.
 */
export const updateMyTaskStatus = async (id: number, completed: boolean): Promise<Task> => {
  const response = await axios.put<Task>(`/api/user/tasks/${id}/status`, { completed });
  return response.data;
}

/**
 * Creates a batch of tasks (supervisor view).
 * @param projectId The ID of the project to create tasks for.
 * @param taskRequest The data for the batch task creation.
 * @returns A promise that resolves to an array of Task objects.
 */
export const createBatchTasks = async (projectId: number, taskRequest: TaskRequest): Promise<Task[]> => {
  const response = await axios.post<Task[]>(`/api/supervisor/projects/${projectId}/batch-tasks`, taskRequest);
  return response.data;
}

/**
 * Gets the tasks associated with a project.
 * @param projectId The ID of the project.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getProjectTasks = async (projectId: number): Promise<Task[]> => {
  try {
    // Check cache first
    const cacheKey = `project-tasks-${projectId}`;
    const cachedData = taskCache.get(cacheKey);
    
    if (cachedData && (Date.now() - cachedData.timestamp) < CACHE_EXPIRY) {
      console.log('Using cached project tasks data for project:', projectId);
      return cachedData.tasks;
    }
    
    // 获取当前用户信息
    const userStore = useUserStore();
    const isSupervisor = userStore.isSupervisor;
    
    // 根据角色选择不同的API路径
    let apiUrl = '';
    if (isSupervisor) {
      apiUrl = `/api/supervisor/projects/${projectId}/batch-tasks`;
    } else {
      apiUrl = `/api/user/projects/${projectId}/tasks`;
    }
    
    console.log('Fetching tasks for project:', projectId, 'using API:', apiUrl);
    const response = await axios.get<Task[]>(apiUrl);
    
    // Ensure we have an array (even if empty)
    const tasks = Array.isArray(response.data) ? response.data : [];
    
    // Cache the results
    taskCache.set(cacheKey, {
      tasks,
      timestamp: Date.now()
    });
    
    console.log(`Retrieved ${tasks.length} tasks for project:`, projectId);
    return tasks;
  } catch (error) {
    console.error('Error fetching project tasks:', error);
    // Return empty array instead of throwing error to prevent UI crashes
    return [];
  }
}

/**
 * Updates the completion status of a task.
 * @param taskId The ID of the task to update.
 * @param completed Whether the task is completed or not.
 * @returns A promise that resolves to a Task object.
 */
export const updateTaskCompletionStatus = async (taskId: number, completed: boolean): Promise<Task> => {
  const response = await axios.put<Task>(`/api/tasks/${taskId}/completion`, { completed });
  return response.data;
};

/**
 * Submits a task file.
 * @param taskId The ID of the task to submit the file for.
 * @param formData The form data containing the file to submit.
 * @returns A promise that resolves to a TaskSubmission object.
 */
export const submitTaskFile = async (taskId: number, formData: FormData): Promise<TaskSubmission> => {
  const response = await axios.post<TaskSubmission>(`/api/user/tasks/${taskId}/submit`, formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  });
  return response.data;
};

/**
 * Gets the submission records for a task.
 * @param taskId The ID of the task to get the submissions for.
 * @returns A promise that resolves to an array of TaskSubmission objects.
 */
export const getTaskSubmissions = async (taskId: number): Promise<TaskSubmission[]> => {
  const response = await axios.get<TaskSubmission[]>(`/api/tasks/${taskId}/submissions`);
  return response.data;
};

/**
 * Gets the details of a submission.
 * @param submissionId The ID of the submission to get the details for.
 * @returns A promise that resolves to a TaskSubmission object.
 */
export const getSubmissionDetail = async (submissionId: number): Promise<TaskSubmission> => {
  const response = await axios.get<TaskSubmission>(`/api/submissions/${submissionId}`);
  return response.data;
};

/**
 * Deletes a submission.
 * @param submissionId The ID of the submission to delete.
 * @returns A promise that resolves to a boolean indicating whether the deletion was successful.
 */
export const deleteSubmission = async (submissionId: number): Promise<boolean> => {
  const response = await axios.delete(`/api/user/submissions/${submissionId}`);
  return response.status === 200;
};

/**
 * Updates the comment for a submission.
 * @param submissionId The ID of the submission to update.
 * @param comment The new comment for the submission.
 * @returns A promise that resolves to a TaskSubmission object.
 */
export const updateSubmissionComment = async (submissionId: number, comment: string): Promise<TaskSubmission> => {
  const response = await axios.put<TaskSubmission>(`/api/user/submissions/${submissionId}/comment`, { comment });
  return response.data;
};

/**
 * Gets all submission records for a user.
 * @returns A promise that resolves to an array of TaskSubmission objects.
 */
export const getUserSubmissions = async (): Promise<TaskSubmission[]> => {
  const response = await axios.get<TaskSubmission[]>(`/api/user/submissions`);
  return response.data;
};

/**
 * Gets all available tasks (tasks not assigned to a project).
 * @param supervisorId The ID of the supervisor.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getAvailableTasks = async (supervisorId: number): Promise<Task[]> => {
  const response = await axios.get<Task[]>(`/api/supervisor/tasks/available?supervisorId=${supervisorId}`);
  return response.data;
};

// ==================== Task Evaluation Interface ====================

/**
 * Creates or updates a task evaluation (supervisor view).
 * @param taskId The ID of the task to evaluate.
 * @param score The score for the task.
 * @param comment The comment for the task.
 * @returns A promise that resolves to a TaskEvaluation object.
 */
export const evaluateTask = async (taskId: number, score: number, comment: string): Promise<TaskEvaluation> => {
  const response = await axios.post<TaskEvaluation>(`/api/supervisor/tasks/${taskId}/evaluate`, { score, comment });
  return response.data;
};

/**
 * Gets a task evaluation (supervisor view).
 * @param taskId The ID of the task to get the evaluation for.
 * @returns A promise that resolves to a TaskEvaluation object.
 */
export const getTaskEvaluation = async (taskId: number): Promise<TaskEvaluation> => {
  const response = await axios.get<TaskEvaluation>(`/api/supervisor/tasks/${taskId}/evaluation`);
  return response.data;
};

/**
 * Deletes a task evaluation (supervisor view).
 * @param taskId The ID of the task to delete the evaluation for.
 * @returns A promise that resolves to a boolean indicating whether the deletion was successful.
 */
export const deleteTaskEvaluation = async (taskId: number): Promise<boolean> => {
  const response = await axios.delete(`/api/supervisor/tasks/${taskId}/evaluation`);
  return response.status === 200;
};

/**
 * Gets a task evaluation (student view).
 * @param taskId The ID of the task to get the evaluation for.
 * @returns A promise that resolves to a TaskEvaluation object.
 */
export const getMyTaskEvaluation = async (taskId: number): Promise<TaskEvaluation> => {
  const response = await axios.get<TaskEvaluation>(`/api/user/tasks/${taskId}/evaluation`);
  return response.data;
};

/**
 * Clears the task cache for a specific project.
 * @param projectId The ID of the project.
 * @returns `true` if the cache was successfully cleared, `false` otherwise.
 */
export const clearProjectTasksCache = (projectId: number) => {
  const cacheKey = `project-tasks-${projectId}`;
  if (taskCache.has(cacheKey)) {
    taskCache.delete(cacheKey);
    console.log(`Cleared task cache for project (ID:${projectId})`);
    return true;
  }
  return false;
};

/**
 * Gets all tasks assigned to a specific student.
 * @param studentId The ID of the student.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getStudentTasks = async (studentId: number): Promise<Task[]> => {
  const response = await axios.get<Task[]>(`/api/supervisor/students/${studentId}/tasks`);
  return response.data;
}

/**
 * Gets tasks with the specified status for a specific student.
 * @param studentId The ID of the student.
 * @param status The status to filter tasks by.
 * @returns A promise that resolves to an array of Task objects.
 */
export const getTasksByStatus = async (studentId: number, status: string): Promise<Task[]> => {
  const response = await axios.get<Task[]>(`/api/supervisor/students/${studentId}/tasks/status/${status}`);
  return response.data;
}